#include "Render.h"
#include <string>



CRender::CRender(void)
{
	m_pDevice = NULL;
	m_pHand = NULL;

	srand(GetTickCount());
	m_fAngle = m_fTime = 0.0f;
	m_bWireFrame = m_bShowSkeleton = false;
}


CRender::~CRender(void)
{
}


void CRender::Init(IDirect3DDevice9* m_pDevice, HWND wnd)
{

	// Create m_light
	ZeroMemory(&m_Light, sizeof(m_Light));
	m_Light.Type      = D3DLIGHT_DIRECTIONAL;
	m_Light.Ambient   = D3DXCOLOR(0.5, 0.5, 0.5, 1.0f);
	m_Light.Diffuse   = D3DXCOLOR(0.9, 0.9, 0.9, 1.0f);
	m_Light.Specular  = D3DXCOLOR(0.5, 0.5, 0.5, 1.0f);
	m_Light.Direction = D3DXVECTOR3(0.0f, -1.0f, 0.0f);
	m_pDevice->SetLight(0, &m_Light);
	m_pDevice->LightEnable(0, true);

	//	Loading the weapons
	m_nActiveWeapon = 0;
	m_Weapons[0].Load("mesh/club.x", m_pDevice);
	m_Weapons[1].Load("mesh/sword.x", m_pDevice);
	m_Weapons[2].Load("mesh/axe.x", m_pDevice);
	m_Weapons[3].Load("mesh/flowers.x", m_pDevice);

	//	Creating DirectX Font
	D3DXCreateFont(m_pDevice, 18, 0, 0, 1, false,  
		DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY,
		DEFAULT_PITCH | FF_DONTCARE, "Arial", &m_pFont);

	//	Loading skinned mesh
	m_SkinnedMesh.Load("mesh/drone.x", m_pDevice);
	m_vAnimations = m_SkinnedMesh.GetAnimations();
	m_nActiveAnimation = m_vAnimations.size() - 3;
	m_SkinnedMesh.SetAnimation((char*)m_vAnimations[m_nActiveAnimation].c_str());

	//	Find left hand bone
	m_pHand = m_SkinnedMesh.FindBone("Bone19");
	m_HandOffset = D3DXVECTOR3(0.5f, 0.0f, -0.07f);

	m_Camera.Init(m_pDevice);



	//	Set sampler state
	for(int nSample = 0; nSample < 8; nSample++)
	{
		m_pDevice->SetSamplerState(nSample, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
		m_pDevice->SetSamplerState(nSample, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
		m_pDevice->SetSamplerState(nSample, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
	}

	//	Setting up the shaders
	m_unitVS.Init(m_pDevice, "shaders/lighting.vs", VERTEX_SHADER);
	m_worldHandle = m_unitVS.GetConstant("matW");
	m_viewProjHandle = m_unitVS.GetConstant("matVP");
	m_sunHandle = m_unitVS.GetConstant("DirToSun");

	m_unitPS.Init(m_pDevice, "shaders/unit.ps", PIXEL_SHADER);

}
void CRender::Update(float fDTime, IDirect3DDevice9* m_pDevice)
{
	//D3DXMATRIX matWorld;
	//D3DXMatrixIdentity(&matWorld);
	//m_pDevice->SetTransform(D3DTS_WORLD, &matWorld);

	////	Update Camera
	//m_Camera.Update(fDTime);

	m_fAngle += fDTime * 0.5f;
	if(m_fAngle > D3DX_PI * 2.0f)
		m_fAngle -= D3DX_PI * 2.0f;

	m_fTime = fDTime * 0.5f;

	if(KEYDOWN('W'))
	{
		m_bWireFrame = !m_bWireFrame;
		Sleep(300);
	}
	else if(KEYDOWN(VK_UP))
	{
		m_nActiveWeapon++;
		if(m_nActiveWeapon >= 4)m_nActiveWeapon = 0;
		Sleep(300);
	}
	else if(KEYDOWN(VK_DOWN))
	{
		m_nActiveWeapon--;
		if(m_nActiveWeapon <= 0)m_nActiveWeapon = 3;
		Sleep(300);
	}
	else if(KEYDOWN(VK_RETURN))
	{
		m_bShowSkeleton = !m_bShowSkeleton;
		Sleep(300);
	}

	else if(KEYDOWN(VK_SPACE))
	{
		m_nActiveAnimation++;
		if(m_nActiveAnimation >= m_vAnimations.size())
			m_nActiveAnimation = 0;

		m_SkinnedMesh.SetAnimation((char*)m_vAnimations[m_nActiveAnimation].c_str());
		Sleep(300);
	}

	else if(KEYDOWN(VK_ESCAPE))
	{
		Quit();
	}

}

HRESULT CRender::Render(IDirect3DDevice9* m_pDevice)
{

	// clear the viewport
	m_pDevice->Clear(0L , NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x0000ffff, 1.0f, 0L); 


	//Set camera
	D3DXMATRIX view, proj, world;
	D3DXMatrixLookAtLH(&view, &D3DXVECTOR3(0.0f, 10.0f, -50.0f), &D3DXVECTOR3(0.0f, 4.0f, 0.0f), &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
	D3DXMatrixOrthoLH(&proj, 10.0f, 9.0f, 0.1f, 1000.0f);

	//Set Skeleton to rotate around the Y-axis
	D3DXMATRIX r, s;
	D3DXMatrixRotationYawPitchRoll(&r, m_fAngle, 0.0f, 0.0f);
	D3DXMatrixScaling(&s, 1.2f, 1.2f, 1.2f);
	world = s * r;

	m_pDevice->SetTransform(D3DTS_VIEW, &view);
	m_pDevice->SetTransform(D3DTS_PROJECTION, &proj);
	m_pDevice->SetTransform(D3DTS_WORLD, &world);

	if(SUCCEEDED(m_pDevice->BeginScene()))
	{

		if(m_bWireFrame)m_pDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
		else m_pDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);

		//////////////////////////////////////////////////////////////////////////
		//							RENDER SKELETON								//
		//////////////////////////////////////////////////////////////////////////
		//m_SkinnedMesh.SetPose(world, NULL, m_fTime);
		//m_SkinnedMesh.RenderSkeleton(NULL, NULL, world);
		//	Use the shaders
		m_unitVS.SetMatrix(m_worldHandle, world);
		m_unitVS.SetMatrix(m_viewProjHandle, view * proj);

		D3DXVECTOR3 sun;
		D3DXVec3Normalize(&sun, &D3DXVECTOR3(0.5f, 1.0f, -0.2f));
		m_unitVS.SetVector3(m_sunHandle, sun);

		m_unitVS.Begin();
		m_unitPS.Begin();

		m_SkinnedMesh.SetPose(world, NULL, m_fTime);
		m_SkinnedMesh.Render(NULL);

		m_unitPS.End();
		m_unitVS.End();

		if(m_bShowSkeleton)
		{
			m_pDevice->Clear(0L, NULL, D3DCLEAR_ZBUFFER, 0x0000ffff, 1.0f, 0L);
			m_SkinnedMesh.RenderSkeleton(NULL, NULL, world);
		}
		//////////////////////////////////////////////////////////////////////////
		//							RENDER MESH									//
		//////////////////////////////////////////////////////////////////////////
		if(m_pHand != NULL)
		{
			D3DXMATRIX boneMatrix = m_pHand->CombinedTransformationMatrix;
			D3DXMATRIX offset, weaponTransform;
			D3DXMatrixTranslation(&offset, m_HandOffset.x, m_HandOffset.y, m_HandOffset.z);

			weaponTransform = offset * boneMatrix * world;

			m_pDevice->SetTransform(D3DTS_WORLD, &weaponTransform);
			m_pDevice->SetRenderState(D3DRS_LIGHTING, true);
			m_Weapons[m_nActiveWeapon].Render();
		}



		RECT r[] = {{10, 10, 0, 0}, {10, 30, 0, 0}, {10, 50, 0, 0}, {10, 90, 0, 0}, {10, 110, 0, 0}};
		m_pFont->DrawText(NULL, "Space: Change Animation", -1, &r[0], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);
		m_pFont->DrawText(NULL, "Return: Show Skeleton On/Off", -1, &r[1], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);
		m_pFont->DrawText(NULL, "W: Wireframe On/Off", -1, &r[2], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);

		std::string str = "Active Animation: " + m_vAnimations[m_nActiveAnimation];
		m_pFont->DrawText(NULL, str.c_str(), -1, &r[3], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);

		m_pFont->DrawText(NULL, "Up or Down: Change Weapon", -1, &r[4], DT_LEFT | DT_TOP | DT_NOCLIP, 0xff000000);

		// End the scene.
		m_pDevice->EndScene();
		m_pDevice->Present(0, 0, 0, 0);
	}
	return S_OK;
}
void CRender::Cleanup()
{
	try
	{
		m_pFont->Release();
	}
	catch (...)
	{

	}

}
void CRender::Quit()
{

	PostQuitMessage(0);
}

